package com.danbay.cloud.deviceaccess.service;

import com.danbay.cloud.base.constants.DeviceType;
import com.danbay.cloud.base.constants.WmWarning;
import com.danbay.cloud.device.api.dto.ReportDataDto;
import com.danbay.cloud.device.api.dto.ReportRelayDto;
import com.danbay.cloud.device.api.dto.WiredMeterDataReportDto;
import com.danbay.cloud.deviceaccess.api.dto.*;
import com.danbay.cloud.deviceaccess.api.dto.lock.*;
import com.danbay.cloud.deviceaccess.api.dto.meter.ReportRelay;
import com.danbay.cloud.deviceaccess.api.dto.meter.ReportVolt;
import com.danbay.cloud.deviceaccess.api.dto.meter.ReportWater;
import com.danbay.cloud.deviceaccess.api.service.IDeviceReportService;
import com.danbay.cloud.deviceaccess.client.LockDeviceReportClient;
import com.danbay.cloud.deviceaccess.client.MeterDeviceReportClient;
import com.danbay.cloud.lock.device.api.dto.AccessReportDto;
import com.danbay.cloud.lock.device.api.dto.DataSyncReportDto;
import com.danbay.cloud.lock.device.api.dto.OpenDoorReportDto;
import com.danbay.cloud.lock.device.api.dto.WarningReportDto;
import com.danbay.framework.exception.BusinessException;
import com.danbay.framework.utils.DateUtils;
import com.danbay.framework.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 设备数据上报服务
 *
 * @author SJG
 *         2017/11/21.
 */
@Service
@Slf4j
public class DeviceReportService implements IDeviceReportService {

    private final DeviceCacheService deviceCacheService;

    private final MeterDeviceReportClient meterDeviceReportClient;

    private final LockDeviceReportClient lockDeviceReportClient;

    @Autowired
    public DeviceReportService(DeviceCacheService deviceCacheService, MeterDeviceReportClient meterDeviceReportClient, LockDeviceReportClient lockDeviceReportClient) {
        this.deviceCacheService = deviceCacheService;
        this.meterDeviceReportClient = meterDeviceReportClient;
        this.lockDeviceReportClient = lockDeviceReportClient;
    }

    /**
     * 3.1	水表水量统计信息上报
     *
     * @param reportWm 水表水量统计信息
     * @throws BusinessException
     */
    @Override
    public void reportWm(ReportWm reportWm) throws BusinessException {
        if (StringUtils.isNotEmpty(reportWm.getDevId())){
            //无线电表数据读取方案
            log.info("水表水量提交云端成功!devId:{},meterCount:{}", reportWm.getDevId(), reportWm.getValue());
            checkReg(reportWm.getDevId());
            meterDeviceReportClient.dataReport(ReportDataDto.builder().devId(reportWm.getDevId())
                    .date(DateUtils.now(DateUtils.YMDHMS2))
                    .meterCount(reportWm.getValue()).build());
        }
    }

    /**
     * 3.2	水表报警信息上报
     *
     * @param wmWarning 水表报警信息
     * @throws BusinessException 业务异常
     */
    @Override
    public void reportWmWarning(ReportWmWarning wmWarning) throws BusinessException {
        log.warn("水表报警信息:devId:{},code:{},warning:{}",
                wmWarning.getDevId(), wmWarning.getCodeValue(),
                WmWarning.getPhrase(wmWarning.getCodeValue()));
    }

    /**
     * 3.1	电表电能量信息上报
     *
     * @param reportKwh 电表电能量信息
     * @throws BusinessException
     */
    @Override
    public void reportKwh(ReportKwh reportKwh) throws BusinessException {
//        checkReg(reportKwh.getDevId());
//        meterDeviceReportClient.dataReport(new ReportDataDto(reportKwh.getDevId(), reportKwh.getValue(), DateUtils.now(DateUtils.YMDHMS2),));
        if (StringUtils.isNotEmpty(reportKwh.getDevId())){
            //无线电表数据读取方案
            checkReg(reportKwh.getDevId());
            meterDeviceReportClient.dataReport(ReportDataDto.builder().devId(reportKwh.getDevId())
                                                            .date(DateUtils.now(DateUtils.YMDHMS2))
                                                            .meterCount(reportKwh.getValue()).build());
        }
        if (StringUtils.isNotEmpty(reportKwh.getNumber())){
            //无线电表读取方案
            meterDeviceReportClient.wiredDataReport(WiredMeterDataReportDto.builder()
                                                                    .meterCount(reportKwh.getValue())
                                                                    .number(reportKwh.getNumber())
                                                                    .readDate(DateUtils.now(DateUtils.YMDHMS2))
                                                                    .build());
        }
        log.info("电表电能量信息提交云端成功!devId:{},meterCount:{}", reportKwh.getDevId(), reportKwh.getValue());
    }

    /**
     * 3.6	电表报警信息上报
     *
     * @param emWarning 电表报警信息
     * @throws BusinessException 业务异常
     */
    @Override
    public void reportWmWarning(ReportEmWarning emWarning) throws BusinessException {
//        log.warn("电表报警信息:devId:{},code:{},warning:{}",
//                emWarning.getDevId(), emWarning.getCodeValue(),
//                EmWarning.getPhrase(emWarning.getCodeValue()));
        DeviceReg deviceReg = deviceCacheService.getDeviceReg(emWarning.getDevId());
        DeviceType deviceType = DeviceType.parse(deviceReg.getSn());
        if (deviceType == DeviceType.LOCK_IN || deviceType == DeviceType.LOCK_OUT) {
            lockDeviceReportClient.warningReport(WarningReportDto.builder()
                    .deviceId(emWarning.getDevId())
                    .code(emWarning.getCode())
                    .time(DateUtils.parse("20"+emWarning.getTime(),DateUtils.YMDHMS2).toDate())
                    .build());
        }
        if (deviceType == DeviceType.EM_METER || deviceType == DeviceType.WATER_METER) {
            //TODO
        }
    }

    @Override
    public void reportRelay(ReportRelay reportRelay) throws BusinessException {
        log.info("电表的继电器信息上报:deviceId:{},value:{}",reportRelay.getDeviceId(),reportRelay.isValue());
        meterDeviceReportClient.reportRelay(ReportRelayDto.builder()
                                .deviceId(reportRelay.getDeviceId())
                                .value(reportRelay.isValue()).build());
    }

    @Override
    public void reportWater(ReportWater reportWater) throws BusinessException {
        log.info("水表-表号:{}上报水量信息",reportWater.getNumber());
        meterDeviceReportClient.wiredDataReport(WiredMeterDataReportDto.builder()
                                                    .meterCount(reportWater.getFlow_value())
                                                    .number(String.valueOf(reportWater.getNumber()))
                                                    .readDate(DateUtils.now(DateUtils.YMDHMS2))
                                                    .build());
    }

    /**
     * 门锁开门上报
     * @param openDoorReport
     * @throws BusinessException
     */
    @Override
    public void reportOpenDoor(OpenDoorReport openDoorReport) throws BusinessException {
        //非法注册的设备不进行处理
        checkReg(openDoorReport.getDeviceId());
        log.info("门锁的开门信息上报:deviceId:{},type:{},alias:{},time:{}",
                openDoorReport.getDeviceId(),openDoorReport.getType(),openDoorReport.getAlias(),
                openDoorReport.getTime());
        lockDeviceReportClient.openDoorReport(OpenDoorReportDto.builder()
                                                    .deviceId(openDoorReport.getDeviceId())
                                                    .alias(openDoorReport.getAlias())
                                                    .type(openDoorReport.getType())
                                                    .power(openDoorReport.getPower())
                                                    .time(openDoorReport.getTime())
                                                    .voltage(openDoorReport.getVoltage()).build());
    }

    /**
     * 门锁的权限动态处理
     * @param accessReport
     * @throws BusinessException
     */
    @Override
    public void lockAccess(AccessReport accessReport) throws BusinessException {
        checkReg(accessReport.getDeviceId());
        log.info("门锁权限上报信息:devId:{},type:{},action:{},alias:{},time:{},op_code:{}",
                accessReport.getDeviceId(),accessReport.getType(),accessReport.getAction(),
                accessReport.getAlias(),accessReport.getTime(),accessReport.getOp_code());
        lockDeviceReportClient.accessReport(AccessReportDto.builder()
                                    .deviceId(accessReport.getDeviceId())
                                    .type(accessReport.getType())
                                    .action(accessReport.getAction())
                                    .alias(accessReport.getAlias())
                                    .time(DateUtils.parse("20"+accessReport.getTime(),
                                            DateUtils.YMDHMS2).toDate())
                                    .opCode(accessReport.getOp_code())
                                    .build());
    }

    /**
     * 门锁锁舌上报
     * @throws BusinessException
     */
    @Override
    public void tongueReport(TongueReport tongueReport) throws BusinessException {
        checkReg(tongueReport.getDeviceId());
        log.info("门锁的锁舌信息上报:deviceId:{},oblique:{},square:{},sensor:{},often_open:{},time:{}",
                tongueReport.getDeviceId(),tongueReport.isOblique(),tongueReport.isSquare(),
                tongueReport.isSensor(),tongueReport.isOften_open(),tongueReport.getTime());
//        deviceInfoServiceClient.tongueReport(TongueReportDto.builder()
//                                                            .deviceId(tongueReport.getDeviceId())
//                                                            .oblique(tongueReport.isOblique())
//                                                            .square(tongueReport.isSquare())
//                                                            .sensor(tongueReport.isSensor())
//                                                            .often_open(tongueReport.isOften_open())
//                                                            .time(tongueReport.getTime())
//                                                            .build());
    }

    @Override
    public void aliasResultReport(AliasResult aliasResult) throws BusinessException {
        checkReg(aliasResult.getDeviceId());
        log.info("设备-门锁:{}的别名更新结果上报:type:{},old_alias:{},new_alias:{},time:{},op_code:{}",
                    aliasResult.getDeviceId(),aliasResult.getOldAlias(),aliasResult.getNewAlias(),
                    aliasResult.getTime(),aliasResult.getOpCode());
//        lockDeviceReportClient.
    }

    /**
     * 门锁的数据同步
     * @param dataSync
     * @throws BusinessException
     */
    @Override
    public void dataSyncReport(DataSync dataSync) throws BusinessException {
        checkReg(dataSync.getDeviceId());
        log.info("设备-门锁:{}的数据同步信息:power:{},steward_cap:{},user_cap:{},temp_cap:{}," +
                "total_cap:{}",dataSync.getPower(),dataSync.getStewardCap(),dataSync.getUserCap(),
                dataSync.getTempCap(),dataSync.getTotalCap());
        DataSyncReportDto dataSyncReportDto = new DataSyncReportDto();
        BeanUtils.copyProperties(dataSync,dataSyncReportDto);
        lockDeviceReportClient.dataSyncReport(dataSyncReportDto);
    }


    @Override
    public void reportPower(ReportVolt reportVolt) throws BusinessException {

    }

    @Override
    public void reportVolt(ReportVolt reportVolt) throws BusinessException {

    }

    @Override
    public void reportCurrent(ReportVolt reportVolt) throws BusinessException {

    }

    @Override
    public void reportPF(ReportVolt reportVolt) throws BusinessException {

    }

    @Override
    public void passSyncReport(Alias alias) throws BusinessException {

    }

    /**
     * 检查设备是否注册
     *
     * @param devId 设备id
     * @throws BusinessException
     */
    private void checkReg(String devId) throws BusinessException {
        if (!deviceCacheService.devIdIsRegistered(devId)) {
            throw new BusinessException("设备:" + devId + "还未注册!");
        }
    }
}
